
#-------------------------------------------------
#
# Basic Makefile to get rid of arduino's GUI (and .ino files)
#
# How it works:
# - the user gives a list of .c/.cc /.cpp 
#   CALLED USR_SRCS
# - generate (once) a "core.a" lib containong all the necessary
#   code from arduino (comprizing the generic "main")
# - compile our own code
# - link all together to get a "elf"
# - objcopy the "elf" to a "hex" file
# - upload the hex


what:
	@echo "Make what ???? (compile,upload,clean)"

#-------------------------------------------------
# compilation
#-------------------------------------------------
# avr-xxx bin tools are installed in standard places (/usr/bin)
CC=avr-gcc
CPP=avr-g++
AR=avr-ar
OBJ_COPY=avr-objcopy
LOADER=avrdude


# dev files are installed in /usr/share, and must be explicitely refered
ARDUINO_TOP=/usr/share/arduino
INCLS=\
  -I$(ARDUINO_TOP)/hardware/arduino/cores/arduino \
  -I$(ARDUINO_TOP)/hardware/arduino/variants/mega 

MCU=atmega2560
F_CPU=16000000

# C flags are used both to compile arduino and user code
GENERAL_FLAGS=\
   -c -g -Os -Wall -ffunction-sections -fdata-sections \
   -mmcu=$(MCU) -DF_CPU=$(F_CPU)L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=105
CPP_FLAGS = $(GENERAL_FLAGS) -fno-exceptions
CC_FLAGS  = $(GENERAL_FLAGS)

# Everything generated goes there
OBJDIR=./objs

# User code, must be defined:
# USR_TARGET = name for the bin
# USR_SRCS   = list of .c,.cc,.cpp ONLY

define compile_c_rule
USR_OBJS+=$(addprefix $(OBJDIR)/, $(notdir $(basename $(1)))).o
$(addprefix $(OBJDIR)/, $(notdir $(basename $(1)))).o: $(1)
	$(CC) $(CC_FLAGS) $(USR_CFLAGS) $(INCLS) $(USR_INCLS) $$< -o $$@ 
endef

define compile_cpp_rule
USR_OBJS+=$(addprefix $(OBJDIR)/, $(notdir $(basename $(1)))).o
$(addprefix $(OBJDIR)/, $(notdir $(basename $(1)))).o: $(1)
	$(CPP) $(CPP_FLAGS) $(USR_CPP_FLAGS) $(INCLS) $(USR_INCLS) $$< -o $$@ 
endef

USR_C=$(filter %.c, $(USR_SRCS))
USR_CPP=$(filter %.cc, $(USR_SRCS))
USR_CPP+=$(filter %.cpp, $(USR_SRCS))

$(foreach src,$(USR_C),$(eval $(call compile_c_rule, $(src))))

$(foreach src,$(USR_CPP),$(eval $(call compile_cpp_rule, $(src))))

#all: $(OBJDIR) $(OBJS)
compile: $(OBJDIR) $(OBJDIR)/$(TARGET).hex

# link my code and the core.a 
$(OBJDIR)/$(TARGET).elf: $(OBJDIR)/core.a $(USR_OBJS)
	$(CC) -Os -Wl,--gc-sections,--relax -mmcu=$(MCU) -o $@ \
		$(USR_OBJS) $(OBJDIR)/core.a -L$(OBJDIR) -lm

# elf -> eep + hex 
$(OBJDIR)/$(TARGET).hex: $(OBJDIR)/$(TARGET).elf
	$(OBJ_COPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load \
      --no-change-warnings --change-section-lma .eeprom=0 $<  $(OBJDIR)/$(TARGET).eep
	$(OBJ_COPY) -O ihex -R .eeprom $< $@

# upload
upload: $(OBJDIR)/$(TARGET).hex
	$(LOADER) -C$(ARDUINO_TOP)/hardware/tools/avrdude.conf -v -patmega2560 \
     -cwiring -P/dev/ttyACM0 -b115200 -D -Uflash:w:$(OBJDIR)/$(TARGET).hex:i

#/usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cwiring -P/dev/ttyACM0 -b115200 -D -Uflash:w:/tmp/build1928257561581363585.tmp/led_arduino_puzzle_loop.cpp.hex:i

$(OBJDIR):
	mkdir -p $@

$(OBJDIR)/%.o: %.cpp
	$(CPP) $(CPP_FLAGS) $(INCLS) $*.cpp -o $@ 

#
# These are all the .o files for core.a
#

CORE_OBJS=\
  $(OBJDIR)/malloc.o \
  $(OBJDIR)/realloc.o \
  $(OBJDIR)/WInterrupts.o \
  $(OBJDIR)/wiring.o \
  $(OBJDIR)/wiring_digital.o \
  $(OBJDIR)/wiring_analog.o \
  $(OBJDIR)/wiring_pulse.o \
  $(OBJDIR)/wiring_shift.o \
  $(OBJDIR)/CDC.o \
  $(OBJDIR)/HardwareSerial.o \
  $(OBJDIR)/HID.o \
  $(OBJDIR)/IPAddress.o \
  $(OBJDIR)/main.o \
  $(OBJDIR)/new.o \
  $(OBJDIR)/Print.o \
  $(OBJDIR)/Stream.o \
  $(OBJDIR)/Tone.o \
  $(OBJDIR)/USBCore.o \
  $(OBJDIR)/WMath.o \
  $(OBJDIR)/WString.o \

COREDIR=$(ARDUINO_TOP)/hardware/arduino/cores/arduino

# Sources are either .c or .cpp, in COREDIR or COREDIR/avr-libc,
# let gmake find the right one, according to these 2 generic rules:

$(OBJDIR)/%.o: $(COREDIR)/avr-libc/%.c
	$(CC) $(CC_FLAGS) $(INCLS) $< -o $@ 

$(OBJDIR)/%.o: $(COREDIR)/%.c
	$(CC) $(CC_FLAGS) $(INCLS) $< -o $@ 

$(OBJDIR)/%.o: $(COREDIR)/%.cpp
	$(CPP) $(CPP_FLAGS) $(INCLS) $< -o $@ 

# build the library 

$(OBJDIR)/core.a: $(CORE_OBJS)
	$(AR) rcs $@ $(CORE_OBJS)

# minimal arduino code to link 
#
#cores/arduino/avr-libc/malloc.c
#cores/arduino/avr-libc/realloc.c
#cores/arduino/WInterrupts.c
#cores/arduino/wiring.c
#cores/arduino/wiring_digital.c
#cores/arduino/wiring_analog.c
#cores/arduino/wiring_pulse.c
#cores/arduino/wiring_shift.c
#cores/arduino/CDC.cpp
#cores/arduino/HardwareSerial.cpp
#cores/arduino/HID.cpp
#cores/arduino/IPAddress.cpp
#cores/arduino/main.cpp
#cores/arduino/new.cpp
#cores/arduino/Print.cpp
#cores/arduino/Stream.cpp
#cores/arduino/Tone.cpp
#cores/arduino/USBCore.cpp
#cores/arduino/WMath.cpp
#cores/arduino/WString.cpp


clean:
	/bin/rm -rf $(OBJDIR)/*
